#ifndef APPWINDOW_H
#define APPWINDOW_H


#include "myinput.h"
#include "../gl/mygl.h"
#include "../core/vector2.h"
#include "../core/foreach.h"
#include "../ut/UTManager.h"
#include "../ut/UTManager.h"
#include "../gl/GLTexture.h"
#include "../gl/GLModel.h"
#include "../gl/GLFont.h"
#include "Audio.h"

class GLClient;
union GLEvent;

enum GLEngineTransition
{
    TRA_None = 0,
    TRA_FadeIn,
    TRA_FadeOut
};

class GLEngine
{
public:
	GLEngine(const char *title, int width, int height, int bpp, bool fullscreen, int vsync, int multisamples);
	virtual ~GLEngine();

public:

	bool doEvents();
	void beginDraw();
	void endDraw();
	void quit(int ret);
    void sendEvent(GLEvent& e);
	inline void sleep(int ms) const		{ glfwSleep(ms / 1000.0); }
	inline void wait() const 			{ glfwWaitEvents(); }

	inline int getTicks() const			{ return (int)(glfwGetTime() * 1000); }
	inline float getTime() const		{ return (float)glfwGetTime(); }
	inline int getWidth() const			{ return winWidth; }
	inline int getHeight() const		{ return winHeight; }
	inline bool isFullscreen() const	{ return winFullscreen; }
	inline bool isVSync() const 		{ return winVSync; }
	inline int isActive() const 		{ return glfwGetWindowParam(GLFW_ACTIVE); }

    inline void setMaxFPS(float fps)    { max_fps = fps; }
    inline void setSize(int w, int h)   { winWidth = w; winHeight = h; }

	//client allocator
	template <class T> T* createClient(const char* name)
	{
        T* new_cli = new T(this);
        new_cli->setName(name);
        m_Clients.push_back(new_cli);
        return new_cli;
    }
    //manage clients
	GLClient* getClient(const char* name);
    int runClient(const char* name);
    void changeClient(const char* name);
	inline GLClient* getCurrentClient() { return client; }

	//resources
	GLTexture* 	getTexture(const char* file_name, int flags);
	GLModel* 	getModel(const char* file_name, float scale = 1.0f, int flags = 0);
    GLFont*     getFont(const char* file_name);
    void releaseTexture(GLTexture* tex);
    void releaseModel(GLModel* mdl);
    void releaseFont(GLFont* fnt);

    inline CAudio* initAudio(int cnt)  { audio = new CAudio(this, cnt); return audio; }
    inline CAudio* getAudio() const { return audio; }

    void initConsole(GLFont* font, int max_lines);
    void pushConsoleLine(const String& s, Color c = Color::White);
    inline bool isConsoleVisible() { return console_visible; }

    void startTransition(GLEngineTransition trans, float timeout, int id);
    void stopTransition();

private:
    //common
	int         winWidth;
	int         winHeight;
	bool        winFullscreen;
	bool        winVSync;
	float       max_fps;
	CAudio*     audio;
    GLClient*   client;
    GLClient*   next_client;
    int         quit_code;
	UTManager<GLTexture>    m_TextureManager;
	UTManager<GLModel>      m_ModelManager;
	UTManager<GLFont>       m_FontManager;
	std::list<GLClient*>    m_Clients;
    //console
    struct ConLine
    {
        String  cmd;
        Color   col;
    };
    GLFont*     console_font;
    bool        console_visible;
    int         console_max_lines;
    String      console_cur_line;
    std::vector<ConLine> console_lines;
    //transition
    GLEngineTransition  trans_mode;
    float               trans_timeout;
    float               trans_start_time;
    int                 trans_id;
};

#endif // APPWINDOW_H
